/*
 * REFEventReactor.h
 *
 *  Created on: Jun 18, 2013
 *      Author: Lucifer
 */

#ifndef REFEVENTREACTOR_H_
#define REFEVENTREACTOR_H_

#include "REFServiceRegistry.h"
#include "REFEventInterrupter.h"
#include "REFTimerService.h"

namespace BFX
{

class REFTimerContext;
class REFTimerQueue;
class REFTimer;

/**
 *
 */
class REFTimerQueueSet : public REFObject
{
public:
	/**
	 * Adds a timer queue to the set.
	 * @param pTimers
	 */
	void Add(REFTimerQueue* pTimers);
	/**
	 * Rmeoves a timer queue from the set.
 	 * @param pTimers
	 */
	void Remove(REFTimerQueue* pTimers);
	/**
	 * Determines whether all queues in the set are empty.
	 * @returns True if empty; otherwise false.
	 */
	bool IsEmpty() const;

	/**
	 * Gets the wait interval in microseconds.
	 * @param lMaxWaitDuration The max wait duration.
	 * @returns The wait interval.
	 */
	long GetWaitInterval(long lMaxWaitInterval) const;

	/**
	 * Dequeues all ready timer contexts.
	 * @param[out] pContexts The list uses to contain all ready contexts.
	 */
	void DequeueReadyContexts(REFEventContextList* pContexts);
	/**
	 * Dequeues all timer contexts.
	 * @param[out] pContexts The list uses to contain all contexts.
	 */
	void DequeueAllContexts(REFEventContextList* pContexts);

private:
	REFTimerQueue*	m_pFirst;
};

/**
 *
 */
class REFEventReactor : public REFServiceBase<REFEventReactor>
{
public:
	/**
	 * Types of events handled by the reactor
	 */
	enum EVENT_TYPE
	{
		READ_EVENT			= 0,
		WRITE_EVENT			= 1,
		EXCEPT_EVENT		= 2,
		MAX_SELECT_EVENTS	= 3,
#if defined(_WIN32) || defined(__CYGWIN__)
		CONNECT_EVENT		= 3,
		MAX_EVENTS			= 4,
#else
		CONNECT_EVENT		= 1,
		MAX_EVENTS			= 3,
#endif
	};

public:
	/**
	 * Initializes a new instance of BFX::REFEventReactor with specified event dispatcher.
	 * @param pDispatcher The event dispatcher.
	 */
	REFEventReactor(REFEventDispatcher* pDispatcher);
	virtual ~REFEventReactor();

	virtual void Shutdown();

	/**
	 * Initializes the reactor for processing tasks.
	 */
	void Restart();

	/**
	 * Adds a new timer event queue into the reactor.
	 * @param pTimerQueue the timer event queue to be add.
	 */
	void AddTimerQueue(REFTimerQueue* pTimerQueue);

	/**
	 * Removes the timer event queue from the reactor.
	 * @param pTimerQueue the timer event queue to be remove.
	 */
	void RemoveTimerQueue(REFTimerQueue* pTimerQueue);

	/**
	 *
	 * @param pTimerQueue
	 * @param pContext
	 */
	void ScheduleTimer(REFTimerQueue* pTimerQueue, REFTimerContext* pContext);

	/**
	 *
	 * @param pTimerQueue
	 * @param pTimer
	 */
	void CancelTimer(REFTimerQueue* pTimerQueue, REFTimer* pTimer);

	/**
	 * Run select once until interrupted or events are ready to be dispatched.
	 *
	 * @param[in] bBlocking The value that indicates whether the event-loop is in blocking mode.
	 * @param[out] pContexts The queue to receive contexts will be completed.
	 */
	void DispatchEvents(bool bBlocking, REFEventContextList* pContexts);

private:
	long	m_lShutdown;
	Mutex	m_mutex;
	REF<REFEventInterrupter>	m_pInterrupter;
	REFEventDispatcher*	m_pDispatcher;
};

} /* namespace BFX */
#endif /* REFEVENTREACTOR_H_ */
